﻿using System;
using SMS.Entities.BaseClasses;
using System.Collections.ObjectModel;
using SMS.Common.Silverlight;
using System.Windows.Input;
using System.Linq;
using System.Collections.Generic;
using SMS.Entities;

namespace SMS.ViewModel.SalesModule
{
    public class SalePageViewModel : BaseNotify
    {
        private Model.SalesModel _model;

        public SalePageViewModel()
        {
            if (App.IsRunning)
            {
                IntializeCommands();
                SaleDetailList = new ObservableCollection<SaleDetailFormViewModel>();
                IntializeModel();
                //SaleDetailList.Add(new SaleDetailFormViewModel());
            }
        }

        private void IntializeCommands()
        {
            NewCommand = new DelegateCommand(New_Clicked);
            AddCommand = new DelegateCommand(AddCommand_Clicked);
            UndoCommand = new DelegateCommand(UndoCommand_Clicked);
            SaveCommand = new DelegateCommand(Save_Clicked);
            CloseReceipt = new DelegateCommand(CloseReceipt_Clicked);
            ShowTransactionCommand = new DelegateCommand(ShowTransactionCommand_Clicked);
        }

        private void IntializeModel()
        {
            _model = new Model.SalesModel();
            _model.SaveSaleHistoryCompleted += new Action<SaleHistory>(_model_SaveSaleHistoryCompleted);
            _model.OnServiceError += new Action<SMSException>(_model_OnServiceError);
            _model.OnGetCustomerBalanceCompleted += new Action<decimal>(_model_OnGetCustomerBalanceCompleted);
        }

        void _model_OnGetCustomerBalanceCompleted(decimal obj)
        {
            CustomerBalance = obj;
            UserMessage = "Customer balance loaded.";
        }

        void _model_OnServiceError(SMSException obj)
        {
            ErrorMessage = obj.Message;
        }

        void _model_SaveSaleHistoryCompleted(SaleHistory obj)
        {
            ReceiptVisiblity = System.Windows.Visibility.Visible;
            SaleHistoryData = obj;
            UserMessage = "Receipt generated with Receipt No " + obj.Sale_ID;
        }

        private Customer _SelectedCustomer;

        public Customer SelectedCustomer
        {
            get { return _SelectedCustomer; }
            set
            {
                _SelectedCustomer = value; OnPropertyChanged("SelectedCustomer");
                if (value != null)
                {
                    _model.GetCustomerBalance(value.Customer_ID);
                    UserMessage = "Getting customer balance...";
                }
            }
        }

        private decimal _CustomerBalance;

        public decimal CustomerBalance
        {
            get { return _CustomerBalance; }
            set { _CustomerBalance = value; OnPropertyChanged("CustomerBalance"); }
        }


        #region Commands & respective Methods

        public ICommand AddCommand { get; private set; }

        private void AddCommand_Clicked(object param)
        {
            if (SaleDetailList == null)
                SaleDetailList = new ObservableCollection<SaleDetailFormViewModel>();
            SaleDetailList.Add(new SaleDetailFormViewModel() { No = SaleDetailList.Count + 1, ClosedMethod = SaleDetailRemoved, SalePropertyChanged = ((s, e) => { PrepareSaleHistory(); }) });

        }

        public ICommand UndoCommand { get; private set; }

        public void UndoCommand_Clicked(object param)
        {
            if (_deletedList != null && _deletedList.Count > 0)
            {
                SaleDetailList.Insert(_deletedList.First().No - 1, _deletedList.First());
                ReorderNumber();
                _deletedList.Remove(_deletedList.First());
            }
        }

        public ICommand SaveCommand { get; private set; }

        public void Save_Clicked(object param)
        {
            if (SelectedCustomer == null)
            {
                ErrorMessage = "Please select customer";
                return;
            }
            if (SaleHistoryData != null && SaleHistoryData.SalesDetailList.Count(k => k.IsLive) > 0)
            {
                SaleHistoryData.Customer = SelectedCustomer;
                SaleHistoryData.SalesMan = new SalesManDetail { SalesMan_ID = 1 };
                _model.SaveSaleHistory(App.LoggedinUserName, SaleHistoryData);
                UserMessage = "Generation receipt...";
            }
            else
            {
                ErrorMessage = "There is no item to sell...";
            }
        }

        public ICommand CloseReceipt { get; private set; }

        public void CloseReceipt_Clicked(object param)
        {
            ReceiptVisiblity = System.Windows.Visibility.Collapsed;
        }

        public ICommand NewCommand { get; private set; }

        public void New_Clicked(object param)
        {
            SaleHistoryData = new SaleHistory();
            SaleDetailList = new ObservableCollection<SaleDetailFormViewModel>();
            _deletedList = new List<SaleDetailFormViewModel>();
            ReceiptVisiblity = System.Windows.Visibility.Collapsed;
        }


        public ICommand ShowTransactionCommand { get; private set; }

        private void ShowTransactionCommand_Clicked(object param)
        {
            if (SelectedCustomer != null)
            {
                var viewModel = Helper.ViewModelLocator.GetViewModel<SMS.ViewModel.Master.CustomerMasterViewModel>();
                viewModel.SelectedMaster = SelectedCustomer;
                viewModel.Loadtransaction_Click(null);
            }
            else
            {
                ErrorMessage = "No customer selected.";
            }
        }


        #endregion

        private ObservableCollection<SaleDetailFormViewModel> _SaleDetailList;
        public ObservableCollection<SaleDetailFormViewModel> SaleDetailList
        {
            get
            {
                PrepareSaleHistory();
                return _SaleDetailList;

            }
            set { _SaleDetailList = value; OnPropertyChanged("SaleDetailList"); }
        }

        private System.Windows.Visibility _ReceiptVisiblity = System.Windows.Visibility.Collapsed;

        public System.Windows.Visibility ReceiptVisiblity
        {
            get { return _ReceiptVisiblity; }
            set { _ReceiptVisiblity = value; OnPropertyChanged("ReceiptVisiblity"); }
        }


        private SaleHistory _SaleHistoryData;

        public SaleHistory SaleHistoryData
        {
            get { return _SaleHistoryData; }
            set { _SaleHistoryData = value; OnPropertyChanged("SaleHistoryData"); }
        }


        private List<SaleDetailFormViewModel> _deletedList;

        private void SaleDetailRemoved(SaleDetailFormViewModel ob)
        {
            SaleDetailList.Remove(ob);
            ReorderNumber();
            if (_deletedList == null)
                _deletedList = new List<SaleDetailFormViewModel>();
            _deletedList.Add(ob);
            PrepareSaleHistory();
        }

        private void ReorderNumber()
        {
            int i = 1;
            SaleDetailList.ToList().ForEach(s => s.No = i++);
        }

        public void PrepareSaleHistory()
        {
            if (_SaleDetailList != null)
            {
                if (SaleHistoryData == null)
                    SaleHistoryData = new SaleHistory();
                SaleHistoryData.TotalSellingPrice = _SaleDetailList.Sum(m => m.SaleDetail.TotalAmount);
                SaleHistoryData.ActualSelliingPrice = _SaleDetailList.Sum(m => m.SaleDetail.BilledAmount);
                SaleHistoryData.Discount = SaleHistoryData.TotalSellingPrice - SaleHistoryData.ActualSelliingPrice;
                SaleHistoryData.Selling_Date = DateTime.Now;
                SaleHistoryData.SalesDetailList = new ObservableCollection<SaleDetail>(_SaleDetailList.Select(m => m.SaleDetail));
                SaleHistoryData.Received = SaleHistoryData.Received;
            }
        }
    }
}
